﻿using System.Collections.Generic;
using System.Web.Mvc;
using ContactManagement;
using EFDataModel;
using System.Linq;

namespace ContactMvc4TB.Helpers.DynamicDataType.Creation
{
    /// <summary>
    /// Modelbinder, der beim Bearbeiten/Anlegen von Dynamischen Datentypen benötigt wird. Hier wird der aktuelle DynamicDataType wieder im Model gesetzt, da dieser
    /// nicht automatisch gefunden wird.
    /// </summary>
    public class EditModelDynamicDataModelBinder : DefaultModelBinder
    {
        /// <summary>
        /// Binden der Daten aus unserem Model mit den Daten die im request Form zurück gegeben werden.
        /// Außerdem wird überprüft ob es sich um valide Eingabewerte für den jeweiligen Eingabetyp handelt. Da die JavaScript Validation auch 
        /// ausgehebelt werden kann muss dies extra noch serverseitig passieren.
        /// </summary>
        protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor)
        {
            //Wenn es sich um unseren Dynamic DataType handelt, der nicht in der Oberfläche gesetzt wird, diesen hier wieder anhand der URL laden und im Model setzten.
            if (propertyDescriptor.PropertyType == typeof(EFDynamicDataType))
            {
                //Keine Fehlerbehandlung durchführen, denn wenn der Wert nicht umgewandelt werden kann, wurde dieser manipuliert und es muss ein Fehler geworfen werden
                string urlDynamicDataTypeId = controllerContext.RouteData.GetRequiredString(WebConstants.IdString);
                EFDynamicDataType currentDynamicDataType = CurrentHttpContext.GetDataModel().EFDynamicDataTypeMenge.Find(int.Parse(urlDynamicDataTypeId));

                //unser Custom PropertyBinding durchführen und den aktuellen Datentyp im Model setzten
                SetProperty(controllerContext, bindingContext, propertyDescriptor, currentDynamicDataType);
            }

            //Wenn es sich um unsere Listeneinträge für den Dynamischen Datentyp "List" handelt, die gesetzt werden sollen, dann diese extra behandeln
            if (propertyDescriptor.PropertyType == typeof(List<DynamicDataTypeListEntry>))
            {
                //Alle Listennamen heraussuchen die mit unserem Prefix für die Listeneinträge beginnen
                var names = controllerContext.HttpContext.Request.Form.AllKeys.Where(x => x.StartsWith(WebConstants.ListEntryName));
                //Alle SortIds zu den Listennamen heraussuchen die mit dem Prefix für die SortId beginnen
                var sortIds = controllerContext.HttpContext.Request.Form.AllKeys.Where(x => x.StartsWith(WebConstants.ListEntrySortId));
                List<DynamicDataTypeListEntry> dynamicDataTypeListEntries = new List<DynamicDataTypeListEntry>();

                foreach (string eItem in names)
                {
                    //die Id befindet sich immer am Ende des Namens z.B.: "ListEntry_12" und hier wird die 12 ermittelt
                    int? listEntryId = WebFunctions.GetControlId(eItem);
                    if (listEntryId.HasValue)
                    {
                        //Ermitteln der SortId aus dem HttpContext
                        string sortId = controllerContext.HttpContext.Request.Form[(sortIds.Where(x => x.EndsWith(string.Format("_{0}", listEntryId.Value))).FirstOrDefault())];
                        dynamicDataTypeListEntries.Add(new DynamicDataTypeListEntry()
                                                           {
                                                               Name = controllerContext.HttpContext.Request.Form[eItem],
                                                               ID = listEntryId.Value,
                                                               //Die passende SortId zum aktuellen Eintrag heraussuchen, dazu die richtige ControlId ermitteln und dann aus dem HttpContext den Inhalt auslesen
                                                               SortId = sortId
                                                           });
                    }
                }

                //Setzten der Liste mit den Eingetragenen Werten
                SetProperty(controllerContext, bindingContext, propertyDescriptor, dynamicDataTypeListEntries);
            }

            //Standard Propertybinding durchführen
            base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
        }

    }
}